#ifndef __MY_LOOPER__
#define __MY_LOOPER__
#include "buffer.hpp"
#include <mutex>
#include <thread>
#include <condition_variable>
#include <functional>
#include <atomic>
namespace mylog
{
    enum class AsyncType
    {
        ASYNC_SAFE,
        ASYNC_UNSAFE
    };
    using Functor = std::function<void(Buffer &)>;
    class AsyncLooper
    {
    public:
        using ptr = std::shared_ptr<AsyncLooper>;
        AsyncLooper(const Functor &callBack, AsyncType looper_type = AsyncType::ASYNC_SAFE)
            : _stop(false), _thread(&AsyncLooper::threadEntry, this), _callBack(callBack), _looper_type(looper_type)
        {
        }
        ~AsyncLooper()
        {
            stop();
        }
        void stop()
        {
            _stop = true;
            _com_cond.notify_one();
            _thread.join();
        }
        void push(const char *data, size_t len)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            if (_looper_type == AsyncType::ASYNC_SAFE)
            {
                _pro_cond.wait(lock, [&]()
                               { return _pro_buffer.writeAbleSize() >= len; });
            }
            _pro_buffer.push(data, len);
            _com_cond.notify_one();
        }

    private:
        void threadEntry() // 线程入口函数
        {
            while (!_stop)
            {
                {
                    // 1.交换两个缓冲区
                    std::unique_lock<std::mutex> lock(_mutex);
                    _com_cond.wait(lock, [&]()
                                   { return _stop || !_com_buffer.empty(); });
                    _com_buffer.swap(_pro_buffer);
                    if(_looper_type == AsyncType::ASYNC_SAFE)
                        _pro_cond.notify_all();
                }
                // 2.处理数据
                _callBack(_com_buffer);
                _com_buffer.reset();
            }
        }

    private:
        Functor _callBack; // 具体对缓冲区数据进行处理的回调函数,由用户自己提供

    private:
        std::atomic<bool> _stop; // 工作器停止标志
        Buffer _pro_buffer;
        Buffer _com_buffer;
        std::mutex _mutex;
        std::condition_variable _pro_cond;
        std::condition_variable _com_cond;
        std::thread _thread; // 异步工作器对应的线程
        AsyncType _looper_type;
    };
}

#endif